package github.sf.fw.tools.var;

import github.sf.fw.utils.RefUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class VarUtil {
    private final static Logger logger = LoggerFactory.getLogger(VarUtil.class);
    private final static String VARIABLE_LEFT = "$_{";
    private final static String VARIABLE_RIGHT = "}";

    @SuppressWarnings("unchecked")
    public static <T> T setVariable(final T target, VariablePool variablePool) {
        Objects.requireNonNull(target);
        Objects.requireNonNull(variablePool);
        if (String.class.isAssignableFrom(target.getClass())) {
            VarInStringResolver resolver = new VarInStringResolver((String) target);
            resolver.resolve();
            return (T) resolver.fillVariable(variablePool);
        }
        RefUtils.doWithFields(target.getClass(), field -> {
            if (field.getType().isAssignableFrom(String.class)) {
                Object fieldValue = RefUtils.get(field, target);
                if (checkVarName((String) fieldValue, false)) {
                    Variable variable = variablePool.getVariable((String) fieldValue);
                    if (variable != null) {
                        RefUtils.set(field, target, variable.getVal());
                    }
                }
            }
        });
        return target;
    }

    public static boolean checkVarName(String varName, boolean warn) {
        if (varName.trim().startsWith(VARIABLE_LEFT) && varName.trim().endsWith(VARIABLE_RIGHT)) {
            return true;
        }
        if (warn) {
            logger.warn("{} 格式错误，应为$_{content}", varName);
        }
        return false;
    }

    public static String wrap(String name) {
        return VARIABLE_LEFT + name + VARIABLE_RIGHT;
    }

    public static String unwrap(String name) {
        if (checkVarName(name, false)) {
            return name.substring(3, name.length() - 1);
        }
        return name;
    }

    public Map<String, Object> toMap(List<Variable> variables) {
        if (variables == null) {
            return new LinkedHashMap<>();
        }
        Map<String, Object> objectMap = new LinkedHashMap<>(variables.size());
        for (Variable variable : variables) {
            objectMap.put(variable.getVariableName(), variable.getVal());
        }
        return objectMap;
    }
}
